﻿using DevExpress.Utils;
using log4net;
using log4net.Config;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using XuanFe.AppLaunch.Common;
using XuanFe.AppLaunch.Common.Security;
using XuanFe.AppLaunch.Config;
using XuanFe.Database.DAL;

namespace XuanFe.AppLaunch
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Process instance = CheckInstance(); // 获取当前应用程序已经执行的实例
            if (instance == null)
            {
                try
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);

                    DevExpress.UserSkins.BonusSkins.Register();
                    DevExpress.Skins.SkinManager.EnableFormSkins();
                    DevExpress.Skins.SkinManager.EnableMdiFormSkins();
                    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-CN");

                    using (WaitDialogForm waitdlg = new WaitDialogForm("正在初始化...", "系统启动中，请稍后"))
                    {
                        waitdlg.Caption = "正在加载配置...";
                        ConfigFactory.Instance.CreateLogConfig();
                        XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(ConfigFactory.Instance.LogConfigFile));
                        ILog logger = log4net.LogManager.GetLogger("AppLogger");

                        if (logger.IsInfoEnabled)
                        {
                            string file = Process.GetCurrentProcess().MainModule.FileName;
                            logger.Info("".PadRight(50, '*'));
                            logger.InfoFormat("启动程序 = {0}", file);
                            logger.InfoFormat("程序版本 = {0}", FileVersionInfo.GetVersionInfo(file).FileVersion);
                        }

                        ServerConfiguration serverConfig = ConfigFactory.Instance.LoadServerConfig();
                        if (serverConfig == null)
                        {
                            logger.Info("加载数据库配置失败");
                            waitdlg.Caption = "加载数据库配置失败";
                            Global.Instance.ErrorDlg(waitdlg, "加载数据库配置失败");
                            return;
                        }

                        logger.Info("正在清理日志文件");
                        waitdlg.Caption = "正在清理日志文件...";
                        ClearLogs(Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), "Logs"), 15);

                        logger.Info("正在连接数据库");
                        waitdlg.Caption = "正在连接数据库...";
                        MySQLHelper.Instance.Server = serverConfig.Server;
                        MySQLHelper.Instance.User = serverConfig.User;
                        //MySQLHelper.Instance.Password = CryptographyHelper.Instance.TripleDESDecryptor("JZTHE2AOX0LCWN1P6GVB8DU4FIY5KS3R", serverConfig.Password);
                        MySQLHelper.Instance.Password = serverConfig.Password;
                        MySQLHelper.Instance.Database = serverConfig.Database;
                        //if (!MySQLHelper.Instance.TestConnect())
                        //{
                        //    logger.InfoFormat("连接数据库({0})失败", MySQLHelper.Instance.Server);
                        //    waitdlg.Caption = string.Format("连接数据库({0})失败", MySQLHelper.Instance.Server);
                        //    Global.Instance.ErrorDlg(waitdlg, string.Format("连接数据库({0})失败", MySQLHelper.Instance.Server));
                        //    return;
                        //}
                        bool blnExit = false;
                        do
                        {
                            if (MySQLHelper.Instance.TestConnect()) break;
                            using (ConnectionForm frm = new ConnectionForm(serverConfig.Server))
                            {
                                if (frm.ShowDialog(waitdlg) != DialogResult.OK)
                                {
                                    // 退出系统
                                    blnExit = true;
                                    break;
                                }
                                serverConfig.Server = frm.Server;
                                ConfigFactory.Instance.SaveServerConfig(serverConfig);
                            }
                        } while (true);
                        if (blnExit)
                        {
                            // 退出系统
                            return;
                        }

                        logger.Info("正在更新数据库");
                        waitdlg.Caption = "正在更新数据库...";
                        DBUpdateDAL.Instance.UpdateDB();
                        if (!DBUpdateDAL.Instance.IsLastVersion())
                        {
                            logger.Info("程序与数据库版本不兼容");
                            logger.Info("程序与数据库版本不兼容");
                            Global.Instance.ErrorDlg("程序与数据库版本不兼容");
                            return;
                        }

                        Application.Run(new MainForm(waitdlg, log4net.LogManager.GetLogger("BizLogger")));
                    }
                }
                finally
                {
                    if (mutex != null)
                    {
                        mutex.ReleaseMutex();
                    }
                    if (LoginInfo.Instance.StaffLogon != null)
                    {
                        Database.BLL.StaffBLL.Instance.Logout(LoginInfo.Instance.StaffLogon.Login);
                        Database.BLL.StaffLogBLL.Instance.InsertLog(LoginInfo.Instance.StaffLogon.Staff.Id, string.Empty, string.Format("于工作站“{0}[{1}]”退出系统", LoginInfo.Instance.ComputerName, LoginInfo.Instance.ComputerIP));
                    }
                }
            }
            else
            {
                HandleRunningInstance(instance);
            }
        }

        #region Windows API

        private const short SW_RESTORE = 9;
        private const int SW_HIDE = 0;//API参数表示隐藏窗口
        private const int SW_SHOW = 5;//API参数表示用当前的大小和位置显示窗口

        [DllImport("user32.dll")]
        private static extern bool IsIconic(IntPtr hWnd);
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hwnd, int cmdShow);
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hwnd);
        [DllImportAttribute("user32.dll")]
        private static extern int FindWindow(string ClassName, string WindowName);
        [DllImport("user32.dll")]
        private static extern int ShowWindow(int handle, int cmdShow);

        #endregion Windows API

        static System.Threading.Mutex mutex;
        /// <summary>
        /// 检查程序实例
        /// </summary>
        /// <returns></returns>
        private static Process CheckInstance()
        {
            bool createNew;
            mutex = new System.Threading.Mutex(true, Application.ProductName, out createNew);
            if (createNew)
            {
                return null;
            }

            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);
            // 遍历与当前进程名称相同的进程列表  
            foreach (Process process in processes)
            {
                // 如果实例已经存在则忽略当前进程  
                if (process.Id != current.Id)
                {
                    // 保证要打开的进程同已经存在的进程来自同一文件路径
                    if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
                        return process;
                }
            }
            return null;
        }
        /// <summary>
        /// 处理运行程序实例
        /// </summary>
        /// <param name="instance"></param>
        private static void HandleRunningInstance(Process instance)
        {
            if (IsIconic(instance.MainWindowHandle))
                ShowWindowAsync(instance.MainWindowHandle, SW_RESTORE);
            SetForegroundWindow(instance.MainWindowHandle);
        }
        /// <summary>
        /// 清除日志文件
        /// </summary>
        /// <param name="dir">日志目录</param>
        /// <param name="days">保留的天数</param>
        private static void ClearLogs(string dir, int days)
        {
            try
            {
                DirectoryInfo dirInfo = new DirectoryInfo(dir);
                FileInfo[] files = dirInfo.GetFiles("*.*", SearchOption.AllDirectories);
                int c = files.Length;
                for (int i = 0; i < c; i++)
                {
                    FileInfo file = files[i];
                    if (file.LastWriteTime >= DateTime.Now.Date.AddDays(0 - days)) continue;
                    file.Delete();
                }
                DirectoryInfo[] dirs = dirInfo.GetDirectories();
                c = dirs.Length;
                for (int i = 0; i < c; i++)
                {
                    DirectoryInfo directory = dirs[i];
                    if (directory.GetFiles("*.*", SearchOption.AllDirectories).Length != 0) continue;
                    directory.Delete(true);
                }
            }
            catch
            {
            }
        }
    }
}
